package com.atguigu.gulimallcart.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.Const.CartConst;
import com.atguigu.common.utils.R;
import com.atguigu.gulimallcart.config.gulimallInterceptor;
import com.atguigu.gulimallcart.feign.ProductSkuFeignService;
import com.atguigu.gulimallcart.service.CartService;
import com.atguigu.gulimallcart.vo.Cart;
import com.atguigu.gulimallcart.vo.CartItem;
import com.atguigu.gulimallcart.vo.SkuInfoVo;
import com.atguigu.gulimallcart.vo.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CartServiceImpl implements CartService {

    ThreadLocal<UserInfo> userInfo = gulimallInterceptor.userInfoThreadLocal;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    ThreadPoolExecutor executor;

    @Resource
    ProductSkuFeignService productSkuFeignService;

    @Override
    public CartItem addCartItem(Long skuId, Integer num) throws ExecutionException, InterruptedException {
        //操作Hash类型的redis
        BoundHashOperations<String, Object, Object> options = getOptions();
        String res = (String) options.get(skuId.toString());
        //购物车中没有该商品的数据

        R skuInfo = productSkuFeignService.getSkuInfo(skuId);
        SkuInfoVo data1 = skuInfo.getData(new TypeReference<SkuInfoVo>() {
        });
        String skuDefaultImg = data1.getSkuDefaultImg();
        String skuTitle = data1.getSkuTitle();
        BigDecimal price = data1.getPrice();


        List<String> skuSaleAttrs1 = productSkuFeignService.getSkuSaleAttrs(skuId);



        if (StringUtils.isEmpty(res)) {
            CartItem item = new CartItem();
            //调用远程商品服务获取sku的基本信息
            CompletableFuture<Void> skuBaseInfoTask = CompletableFuture.runAsync(() -> {
                R info = productSkuFeignService.getSkuInfo(skuId);
                SkuInfoVo data = info.getData(new TypeReference<SkuInfoVo>() {
                });
                item.setCheck(true);
                item.setCount(num);
                item.setImage(data.getSkuDefaultImg());
                item.setPrice(data.getPrice());
                item.setSkuId(skuId);
                item.setTitle(data.getSkuTitle());
            }, executor);

            CompletableFuture<Void> attrTask = CompletableFuture.runAsync(() -> {
                //调用sku销售属性远程服务查询attr
                List<String> skuSaleAttrs = productSkuFeignService.getSkuSaleAttrs(skuId);
                item.setSkuAttr(skuSaleAttrs);
            }, executor);

            //阻塞等待异步任务完成
            CompletableFuture.allOf(skuBaseInfoTask, attrTask).get();


            String s = JSON.toJSONString(item);
            //存入redis
            options.put(skuId.toString(), s);
            //将添加的购物项返回
            return item;
        }
        //之前有该商品，只需修改该商品的num
        else {
            //原始购物车数据
            CartItem item = JSON.parseObject(res, CartItem.class);
            item.setCount(item.getCount() + num);
            //重新放回去
            options.put(skuId.toString(), JSON.toJSONString(item));
            return item;
        }


    }


    private BoundHashOperations<String, Object, Object> getOptions() {
        //放入redis存储
        UserInfo userInfo = this.userInfo.get();
        //已登录的用户
        String key = "";
        if (userInfo.getUserId() != null) {
            key = CartConst.CART_USER_KEY + userInfo.getUserId();
        } else {
            //临时用户
            key = CartConst.CART_USER_KEY + userInfo.getUserKey();
        }
        BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(key);
        return operations;
    }

    @Override
    public CartItem getItemBySkuId(Long skuId) {
        BoundHashOperations<String, Object, Object> options = getOptions();
        String res = (String) options.get(skuId.toString());
        CartItem cartItem = JSON.parseObject(res, CartItem.class);
        return cartItem;
    }

    //展示购物车中的内容
    @Override
    public Cart getCarts() throws ExecutionException, InterruptedException {
        Cart cart = new Cart();
        UserInfo userInfo = this.userInfo.get();
        Long userId = userInfo.getUserId();
        String userKey = userInfo.getUserKey();
        if (userId != null) {
            //展示正式的购物车内容
            String tempKey = CartConst.CART_USER_KEY + userKey;
            //临时购物车也有数据
            if (!StringUtils.isEmpty(tempKey)) {
                List<CartItem> tempCartItems = getCartItems(tempKey);
                //先往redis中存一份
                if (tempCartItems != null && tempCartItems.size() > 0) {

                    for (CartItem tempCartItem : tempCartItems) {
                        //合并商品
                        addCartItem(tempCartItem.getSkuId(), tempCartItem.getCount());
                    }
                    //清空临时购物车中的内容
                    clarCart(tempKey);
                }
            }
            //取出正式购物车中的内容
            String key = CartConst.CART_USER_KEY + userId;
            List<CartItem> cartItems = getCartItems(key);
            cart.setItems(cartItems);

        } else {
            //展示临时购物车内容
            String tempKey = CartConst.CART_USER_KEY + userKey;
            List<CartItem> tempCartItems = getCartItems(tempKey);
            cart.setItems(tempCartItems);
        }

        log.info("返回的cart对象:" + cart);
        return cart;
    }

    /**
     * 获取购物车中的购物项
     *
     * @param tempKey
     * @return
     */
    private List<CartItem> getCartItems(String tempKey) {
        BoundHashOperations<String, Object, Object> options = redisTemplate.boundHashOps(tempKey);
        //redis中存放的临时购物车中的内容(cartItem)
        List<Object> values = options.values();

        if (values != null && values.size() > 0) {
            //收集到的购物项
            List<CartItem> collect = values.stream().map((item) -> {
                String str = (String) item;
                CartItem cartItem = JSON.parseObject(str, CartItem.class);
                return cartItem;
            }).collect(Collectors.toList());
            return collect;
        }
        return null;


    }

    @Override
    public void changeStatus(Long skuId, Integer checked) {
        CartItem item = getItemBySkuId(skuId);
        item.setCheck(checked == 1 ? true : false);
        String itemStr = JSON.toJSONString(item);
        BoundHashOperations<String, Object, Object> options = getOptions();
        options.put(skuId.toString(), itemStr);
    }


    @Override
    public void changeNum(Long skuId, Integer num) {
        CartItem item = getItemBySkuId(skuId);
        item.setCount(num);
        String itemStr = JSON.toJSONString(item);
        BoundHashOperations<String, Object, Object> options = getOptions();
        options.put(skuId.toString(), itemStr);
    }

    //清空临时购物车中的数据
    private void clarCart(String tempKey) {
        redisTemplate.delete(tempKey);
    }

    @Override
    public void delCartItem(Long skuId) {
        BoundHashOperations<String, Object, Object> options = getOptions();
        options.delete(skuId.toString());
    }
}
